home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Experimental BBS Explossion 3
/
Experimental BBS Explossion III.iso
/
games
/
nhak_src.zip
/
AMIDOS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-09-19
|
18KB
|
774 lines
/* SCCS Id: @(#)amidos.c msdos.c - Amiga version 3.0 89/05/01
/* NetHack may be freely redistributed. See license for details. */
/* An assortment of imitations of cheap plastic MSDOS functions.
*/
#define NEED_VARARGS
#include "hack.h"
#undef TRUE
#undef FALSE
#undef COUNT
#undef NULL
#include <libraries/dos.h>
#ifdef LATTICE
#include <proto/exec.h>
#include <proto/dos.h>
#endif
/* Prototypes for functions defined in amidos.c */
void NDECL (flushout);
int NDECL (getpid);
int FDECL (abs, (int x));
int NDECL (tgetch);
int NDECL (dosh);
long FDECL (freediskspace, (char *path));
long FDECL (filesize, (char *file));
void FDECL (eraseall, (char *path,
char *files));
char *FDECL (CopyFile, (char *from,
char *to));
void FDECL (copybones, (int mode));
void NDECL (playwoRAMdisk);
int FDECL (saveDiskPrompt, (int start));
void NDECL (gameDiskPrompt);
void NDECL (read_config_file);
void NDECL (set_lock_and_bones);
void FDECL (append_slash, (char *name));
void FDECL (getreturn, (char *str));
void VDECL (msmsg, (char *fmt, ...));
FILE * FDECL (fopenp, (char *name,
char *mode));
int FDECL (chdir, (char *dir));
void FDECL (msexit, (int code));
static boolean NDECL (record_exists);
static int FDECL (strcmpi, (register char *a, register char *b));
extern char Initialized;
#ifdef AZTEC_C
struct DateStamp *FDECL(DateStamp, (struct DateStamp *));
BPTR FDECL(Lock, (char *, long));
BPTR FDECL(CurrentDir, (BPTR));
BPTR FDECL(Open, (char *, long));
long FDECL(Read, (BPTR, char *, long));
long FDECL(Write, (BPTR, char *, long));
long NDECL(IoErr);
long FDECL(AvailMem, (long));
void *FDECL(malloc, (unsigned int));
char *FDECL(rindex, (char *, int));
char *FDECL(index, (char *, int));
#endif
int Enable_Abort = 0; /* for stdio package */
/* Initial path, so we can find NetHack.cnf */
char PATH[PATHLEN] = "Ram:;df0:;NetHack:";
void
flushout()
{
(void) fflush(stdout);
}
#ifndef getuid
getuid()
{
return 1;
}
#endif
/*
* Actually make up a process id.
* Makes sure one can mess less with saved levels...
*/
int getpid()
{
static short pid;
while (pid == 0) {
struct DateStamp dateStamp;
pid = rnd(30000);
pid += (short) DateStamp(&dateStamp); /* More or less random */
pid ^= (short) (dateStamp.ds_Days >> 16) ^
(short) (dateStamp.ds_Days) ^
(short) (dateStamp.ds_Minute) +
(short) (dateStamp.ds_Tick);
pid %= 30000;
}
return (int)pid;
}
#ifndef getlogin
char *
getlogin()
{
return ((char *) NULL);
}
#endif
int
abs(x)
int x;
{
return x < 0? -x: x;
}
int
tgetch() {
char ch;
ch = WindowGetchar();
return ((ch == '\r') ? '\n' : ch);
}
#ifdef DGK
# include <ctype.h>
/* # include <fcntl.h> */
# define Sprintf (void) sprintf
# ifdef SHELL
int
dosh()
{
pline("No mysterious force prevented you from using multitasking.");
return 0;
}
# endif /* SHELL */
#define ID_DOS1_DISK 'DOS\1'
#define EXTENSION 72
/*
* This routine uses an approximation of the free bytes on a disk.
* How large a file you can actually write depends on the number of
* extension blocks you need for it.
* In each extenstion block there are maximum 72 pointers to blocks,
* so every 73 disk blocks have only 72 available for data.
* The (necessary) file header is also good for 72 data block pointers.
*/
long
freediskspace(path)
char *path;
{
register long freeBytes = 0;
register struct InfoData *infoData; /* Remember... longword aligned */
char fileName[32];
/*
* Find a valid path on the device of which we want the free space.
* If there is a colon in the name, it is an absolute path
* and all up to the colon is everything we need.
* Remember slashes in a volume name are allowed!
* If there is no colon, it is relative to the current directory,
* so must be on the current device, so "" is enough...
*/
{
register char *colon;
strncpy(fileName, path, sizeof(fileName)-1);
fileName[31] = 0;
if (colon = index(fileName, ':'))
colon[1] = '\0';
else
fileName[0] = '\0';
}
if (infoData = malloc(sizeof(struct InfoData))) {
BPTR fileLock;
if (fileLock = Lock(fileName, SHARED_LOCK)) {
if (Info(fileLock, infoData)) {
/* We got a kind of DOS volume, since we can Lock it. */
/* Calculate number of blocks available for new file */
/* Kludge for the ever-full VOID: (oops RAM:) device */
if (infoData->id_UnitNumber == -1 &&
infoData->id_NumBlocks == infoData->id_NumBlocksUsed) {
freeBytes = AvailMem(0L) - 64 * 1024L;
/* Just a stupid guess at the */
/* Ram-Handler overhead per block: */
freeBytes -= freeBytes/16;
} else {
/* Normal kind of DOS file system device/volume */
freeBytes = infoData->id_NumBlocks -
infoData->id_NumBlocksUsed;
freeBytes -= (freeBytes + EXTENSION) / (EXTENSION + 1);
freeBytes *= infoData->id_BytesPerBlock;
}
if (freeBytes < 0)
freeBytes = 0;
}
UnLock(fileLock);
}
free(infoData);
}
return freeBytes;
}
long
filesize(file)
char *file;
{
register BPTR fileLock;
register struct FileInfoBlock *fileInfoBlock;
register long size = 0;
if (fileInfoBlock = malloc(sizeof(struct FileInfoBlock))) {
if (fileLock = Lock(file, SHARED_LOCK)) {
if (Examine(fileLock, fileInfoBlock)) {
size = fileInfoBlock->fib_Size;
}
UnLock(fileLock);
}
free(fileInfoBlock);
}
return size;
}
/*
* On the Amiga, looking if a specific file exists is much faster
* than sequentially reading a directory.
*/
void
eraseall(path, files)
char *path, *files;
{
char buf[FILENAME];
short i;
BPTR fileLock, dirLock;
if (dirLock = Lock(path ,SHARED_LOCK)) {
dirLock = CurrentDir(dirLock);
strcpy(buf, files);
for (i = 0; i <= MAXLEVEL; i++) {
name_file(buf, i);
if (fileLock = Lock(buf, SHARED_LOCK)) {
UnLock(fileLock);
DeleteFile(buf);
} else if (IoErr() == ERROR_DEVICE_NOT_MOUNTED)
break;
}
UnLock(CurrentDir(dirLock));
}
}
/* This size makes that most files can be copied with two Read()/Write()s */
#define COPYSIZE 4096
char *CopyFile(from, to)
char *from, *to;
{
register BPTR fromFile, toFile;
register char *buffer;
register long size;
char *error = NULL;
if (buffer = malloc(COPYSIZE)) {
if (fromFile = Open(from, MODE_OLDFILE)) {
if (toFile = Open(to, MODE_NEWFILE)) {
while (size = Read(fromFile, buffer, (long)COPYSIZE)) {
if (size != Write(toFile, buffer, size)) {
error = "Write error";
break;
}
}
Close(toFile);
} else /* Can't open destination file */
error = "Cannot open destination";
Close(fromFile);
} else /* Cannot open source file. Should not happen. */
error = "Huh?? Cannot open source??";
free(buffer);
return error;
} else /* Cannot obtain buffer for copying */
return "No Memory !";
}
void
copybones(mode)
int mode;
{
BPTR fileLock;
char from[FILENAME], to[FILENAME];
char *frompath, *topath, *status;
short i;
extern int saveprompt;
if (!ramdisk)
return;
frompath = (mode != TOPERM) ? permbones : levels;
topath = (mode == TOPERM) ? permbones : levels;
/* Remove any bones files in `to' directory. */
eraseall(topath, allbones);
/* Copy `from' to `to' */
strcpy(from, frompath);
strcat(from, allbones);
strcpy(to, topath);
strcat(to, allbones);
for (i = 1; i < MAXLEVEL; i++) {
name_file(from, i);
name_file(to, i);
if (fileLock = Lock(from, SHARED_LOCK)) {
UnLock(fileLock);
if (status = CopyFile(from, to))
goto failed;
} else if (IoErr() == ERROR_DEVICE_NOT_MOUNTED) {
status = "disk not present";
goto failed;
}
}
/*
* The last file got there. Remove the ramdisk bones files.
*/
if (mode == TOPERM)
eraseall(frompath, allbones);
return;
/* Last file didn't get there. */
failed:
msmsg("Cannot copy `%s' to `%s'\n(%s)\n", from, to, status);
if (mode == TOPERM) {
msmsg("Bones will be left in `%s'\n",
*frompath ? frompath : hackdir);
return;
} else {
/* Remove all bones files on the RAMdisk */
eraseall(levels, allbones);
playwoRAMdisk();
}
}
void
playwoRAMdisk()
{
msmsg("Do you wish to play without a RAMdisk (y/n) ? ");
/* Set ramdisk false *before* exit'ing (because msexit calls
* copybones)
*/
ramdisk = FALSE;
if (Getchar() != 'y') {
settty("Be seeing you ...\n");
exit(0);
}
set_lock_and_bones();
return;
}
int
saveDiskPrompt(start)
{
extern int saveprompt;
char buf[BUFSIZ], *bp;
BPTR fileLock;
if (saveprompt) {
/* Don't prompt if you can find the save file */
if (fileLock = Lock(SAVEF, SHARED_LOCK)) {
UnLock(fileLock);
return 1;
}
remember_topl();
home();
cl_end();
msmsg("If save file is on a SAVE disk, put that disk in now.\n");
cl_end();
msmsg("File name (default `%s'%s) ? ", SAVEF,
start ? "" : ", <Esc> cancels save");
getlin(buf);
home();
cl_end();
curs(1, 2);
cl_end();
if (!start && *buf == '\033')
return 0;
/* Strip any whitespace. Also, if nothing was entered except
* whitespace, do not change the value of SAVEF.
*/
for (bp = buf; *bp; bp++)
if (!isspace(*bp)) {
strncpy(SAVEF, bp, PATHLEN);
break;
}
}
return 1;
}
/* Return 1 if the record file was found */
static boolean
record_exists()
{
FILE *file;
if (file = fopenp(RECORD, "r")) {
fclose(file);
return TRUE;
}
return FALSE;
}
/* Prompt for game disk, then check for record file.
*/
void
gameDiskPrompt()
{
extern int saveprompt;
if (record_exists())
return;
if (saveprompt) {
(void) putchar('\n');
getreturn("when the GAME disk has been put in");
}
if (!record_exists()) {
msmsg("\n\nWARNING: can't find record file `%s'!\n", RECORD);
msmsg("If the GAME disk is not in, put it in now.\n");
getreturn("to continue");
}
}
/* Read configuration */
void
read_config_file()
{
char tmp_ramdisk[PATHLEN], tmp_levels[PATHLEN];
char buf[BUFSZ], *bufp;
FILE *fp;
extern char plname[];
extern int saveprompt;
tmp_ramdisk[0] = 0;
tmp_levels[0] = 0;
if ((fp = fopenp(configfile, "r")) == NULL) {
msmsg("Warning: no configuration file!\n");
getreturn("to continue");
return;
}
while (fgets(buf, BUFSZ, fp)) {
if (*buf == '#')
continue;
/* remove trailing whitespace */
bufp = index(buf, '\n');
while (bufp > buf && isspace(*bufp))
bufp--;
if (bufp == buf)
continue; /* skip all-blank lines */
else
*(bufp + 1) = 0; /* 0 terminate line */
/* find the '=' */
if (!(bufp = index(buf, '='))) {
msmsg("Bad option line: '%s'\n", buf);
getreturn("to continue");
continue;
}
/* skip whitespace between '=' and value */
while (isspace(*++bufp))
;
/* Go through possible variables */
if (!strncmp(buf, "HACKDIR", 4)) {
strncpy(hackdir, bufp, PATHLEN);
} else if (!strncmp(buf, "RAMDISK", 3)) {
strncpy(tmp_ramdisk, bufp, PATHLEN);
} else if (!strncmp(buf, "LEVELS", 4)) {
strncpy(tmp_levels, bufp, PATHLEN);
} else if (!strncmp(buf, "OPTIONS", 4)) {
parseoptions(bufp, (boolean)TRUE);
if (plname[0]) /* If a name was given */
plnamesuffix(); /* set the character class */
} else if (!strncmp(buf, "SAVE", 4)) {
char *ptr;
if (ptr = index(bufp, ';')) {
*ptr = '\0';
if (*(ptr+1) == 'n' || *(ptr+1) == 'N')
saveprompt = FALSE;
}
(void) strncpy(SAVEF, bufp, PATHLEN);
append_slash(SAVEF);
} else if (!strncmp(buf, "GRAPHICS", 4)) {
unsigned int translate[MAXPCHARS+1]; /* for safety */
int lth;
if ((lth = sscanf(bufp,
"%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
&translate[0], &translate[1], &translate[2],
&translate[3], &translate[4], &translate[5],
&translate[6], &translate[7], &translate[8],
&translate[9], &translate[10], &translate[11],
&translate[12], &translate[13], &translate[14],
&translate[15], &translate[16], &translate[17],
&translate[18], &translate[19], &translate[20],
&translate[21], &translate[22], &translate[23],
&translate[24], &translate[25], &translate[26],
&translate[27], &translate[28], &translate[29],
&translate[30], &translate[31], &translate[32],
&translate[33], &translate[34])) < 0) {
msmsg ("Syntax error in GRAPHICS\n");
getreturn("to continue");
} /* Yuck! Worked only with low-byte first!!! */
assign_graphics(translate, lth);
} else if (!strncmp(buf, "PATH", 4)) {
strncpy(PATH, bufp, PATHLEN);
} else {
msmsg("Bad option line: '%s'\n", buf);
getreturn("to continue");
}
}
fclose(fp);
strcpy(permbones, tmp_levels);
if (tmp_ramdisk[0]) {
strcpy(levels, tmp_ramdisk);
if (strcmpi(permbones, levels)) /* if not identical */
ramdisk = TRUE;
} else
strcpy(levels, tmp_levels);
strcpy(bones, levels);
}
/* Set names for bones[] and lock[] */
void
set_lock_and_bones()
{
if (!ramdisk) {
strcpy(levels, permbones);
strcpy(bones, permbones);
}
append_slash(permbones);
append_slash(levels);
append_slash(bones);
strcat(bones, allbones);
strcpy(lock, levels);
strcat(lock, alllevels);
}
/*
* Add a slash to any name not ending in / or :. There must
* be room for the /.
*/
void
append_slash(name)
char *name;
{
char *ptr;
if (!*name)
return;
ptr = name + (strlen(name) - 1);
if (*ptr != '/' && *ptr != ':') {
*++ptr = '/';
*++ptr = '\0';
}
}
void
getreturn(str)
char *str;
{
int ch;
msmsg("Hit <RETURN> %s.", str);
while ((ch = Getchar()) != '\n')
;
}
void
msmsg VA_DECL(char *, fmt)
VA_START(fmt);
VA_INIT(fmt, char *);
#ifdef LATTICE
{
extern struct Screen *HackScreen;
char buf[100];
vsprintf(buf,fmt,VA_ARGS);
if(HackScreen){
WindowFPuts(buf);
WindowFlush();
} else {
fprintf(stdout,buf);
fflush(stdout);
}
}
#else
vprintf(fmt, VA_ARGS);
(void) fflush(stdout);
#endif
VA_END();
}
/* Follow the PATH, trying to fopen the file.
*/
#define PATHSEP ';'
#undef fopen
FILE *
fopenp(name, mode)
register char *name, *mode;
{
char buf[BUFSIZ], *bp, *pp, lastch;
FILE *fp;
register BPTR theLock;
/* Try the default directory first. Then look along PATH.
*/
strcpy(buf, name);
if (theLock = Lock(buf, SHARED_LOCK)) {
UnLock(theLock);
if (fp = fopen(buf, mode))
return fp;
}
pp = PATH;
while (pp && *pp) {
bp = buf;
while (*pp && *pp != PATHSEP)
lastch = *bp++ = *pp++;
if (lastch != ':' && lastch != '/' && bp != buf)
*bp++ = '/';
strcpy(bp, name);
if (theLock = Lock(buf, SHARED_LOCK)) {
UnLock(theLock);
if (fp = fopen(buf, mode))
return fp;
}
if (*pp)
pp++;
}
return NULL;
}
#endif /* DGK */
#ifdef CHDIR
/*
* A not general-purpose directory changing routine.
* Assumes you want to return to the original directory eventually,
* by chdir()ing to orgdir.
* Assumes -1 is not a valid lock, since 0 is valid.
*/
#define NO_LOCK ((BPTR) -1)
char orgdir[1];
static BPTR OrgDirLock = NO_LOCK;
chdir(dir)
char *dir;
{
if (dir == orgdir) {
/* We want to go back to where we came from. */
if (OrgDirLock != NO_LOCK) {
UnLock(CurrentDir(OrgDirLock));
OrgDirLock = NO_LOCK;
}
} else {
/*
* Go to some new place. If still at the original
* directory, save the FileLock.
*/
BPTR newDir;
if (newDir = Lock(dir, SHARED_LOCK)) {
if (OrgDirLock == NO_LOCK) {
OrgDirLock = CurrentDir(newDir);
} else {
UnLock(CurrentDir(newDir));
}
} else {
return -1; /* Failed */
}
}
/* CurrentDir always succeeds if you have a lock */
return 0;
}
#endif
/* Chdir back to original directory
*/
#undef exit
void
msexit(code)
{
#ifdef CHDIR
extern char orgdir[];
#endif
#ifdef DGK
(void) fflush(stdout);
if (ramdisk)
copybones(TOPERM);
#endif
#ifdef CHDIR
chdir(orgdir); /* chdir, not chdirx */
#endif
CleanUp();
exit(code);
}
/*
* Strcmp while ignoring case. Not general-purpose, so static.
*/
static int strcmpi(a, b)
register char *a, *b;
{
while (tolower(*a) == tolower(*b)) {
if (!*a) /* *a == *b, so at end of both strings */
return 0; /* equal. */
a++;
b++;
}
return 1;
}
/*
* memcmp - used to compare two struct symbols, in lev.c
*/
#if defined(AZTEC_C) && !defined(memcmp)
memcmp(a, b, size)
register unsigned char *a, *b;
register int size;
{
while (size--) {
if (*a++ != *b++)
return 1; /* not equal */
}
return 0; /* equal */
}
#endif